package com.wxw.jwt.shiro;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wxw.jwt.mapper.SysRoleMapper;
import com.wxw.jwt.po.JwtToken;
import com.wxw.jwt.po.SysRole;
import com.wxw.jwt.po.SysUser;
import com.wxw.jwt.service.SysUserService;
import com.wxw.jwt.uitls.JwtUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author wxw
 * @data 2021/8/30 00 :12
 * @description
 */
@Slf4j
public class MyRealm extends AuthorizingRealm {

    @Autowired
    private SysUserService userService;
    @Autowired
    private SysRoleMapper sysRoleMapper;

    // 不写该方法，会报错不支持自定义的token
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        String username = principalCollection.getPrimaryPrincipal().toString();
        SysUser sysUser = userService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
        // 去数据库中查询该用户的角色和权限
        List<SysRole> roles = sysRoleMapper.queryRole(sysUser.getId());
        Set<String> roleSet = new HashSet<>();
        roles.forEach(item -> roleSet.add(item.getCode()));
        authorizationInfo.addRoles(roleSet);
        return authorizationInfo;
    }

    /**
     * 登录认证
     * @param authenticationToken 封装的token(UsernamePasswordToken)
     */
    @SneakyThrows
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // authenticationToken就是JwtToken
        if (authenticationToken.getPrincipal() == null) {
            throw new AuthenticationException("token不合法");
        }
        String token = authenticationToken.getPrincipal().toString();
        if (JwtUtil.isExpired(token)) {
            throw new AuthenticationException("token过期");
        }
        if (!JwtUtil.verify(token,JwtUtil.getUsername(token))) {
            throw new AuthenticationException("token错误");
        }

        return new SimpleAuthenticationInfo(token,token,
                getName()
        );

    }
}

